gsk: Add contains/intersect functions for GskRoundedRect
authorBenjamin Otte <otte@redhat.com>
Mon, 19 Dec 2016 03:39:33 +0000 (04:39 +0100)
committerBenjamin Otte <otte@redhat.com>
Tue, 20 Dec 2016 17:01:12 +0000 (18:01 +0100)
... and use them.

docs/reference/gsk/gsk4-sections.txt
gsk/gskroundedrect.c
gsk/gskroundedrect.h
gtk/gtkcssshadowvalue.c
gtk/gtkroundedbox.c
gtk/gtkroundedboxprivate.h

index 20785e7ff7ff332119274b33b734bce7984e595e..8afc2324527cbc89bb6657c8eb8498fef269be28 100644 (file)
@@ -77,4 +77,7 @@ gsk_rounded_rect_normalize
 gsk_rounded_rect_offset
 gsk_rounded_rect_shrink
 gsk_rounded_rect_is_rectilinear
+gsk_rounded_rect_contains_point
+gsk_rounded_rect_contains_rect
+gsk_rounded_rect_intersects_rect
 </SECTION>
index f1ecc2b4ecf73c97b5f6f4eca9c2141e1b9430d5..a38b96e58c9feedcb897154a80e956d427827fdb 100644 (file)
@@ -290,7 +290,7 @@ gsk_rounded_rect_shrink (GskRoundedRect *self,
  * Returns: %TRUE if the rectangle is rectilinear
  **/
 gboolean
-gsk_rounded_rect_is_rectilinear (GskRoundedRect *self)
+gsk_rounded_rect_is_rectilinear (const GskRoundedRect *self)
 {
   guint i;
 
@@ -304,6 +304,124 @@ gsk_rounded_rect_is_rectilinear (GskRoundedRect *self)
   return TRUE;
 }
 
+gboolean
+ellipsis_contains_point (const graphene_size_t *ellipsis,
+                         const graphene_point_t *point)
+{
+  return (point->x * point->x) / (ellipsis->width * ellipsis->width)
+       + (point->y * point->y) / (ellipsis->height * ellipsis->height) <= 1;
+}
+
+/**
+ * gsk_rounded_rect_contains_point:
+ * @self: a #GskRoundedRect
+ * @point: the point to check
+ *
+ * Checks if the given @point is inside the rounded rectangle. This function
+ * returns %FALSE if the point is in the rounded corner areas.
+ *
+ * Returns: %TRUE if the @point is inside the rounded rectangle
+ **/
+gboolean
+gsk_rounded_rect_contains_point (const GskRoundedRect   *self,
+                                 const graphene_point_t *point)
+{
+  if (!graphene_rect_contains_point (&self->bounds, point))
+    return FALSE;
+
+  if (self->bounds.origin.x + self->corner[GSK_CORNER_TOP_LEFT].width > point->x &&
+      self->bounds.origin.y + self->corner[GSK_CORNER_TOP_LEFT].height > point->y &&
+      !ellipsis_contains_point (&self->corner[GSK_CORNER_TOP_LEFT],
+                                &GRAPHENE_POINT_INIT (
+                                    self->bounds.origin.x + self->corner[GSK_CORNER_TOP_LEFT].width - point->x,
+                                    self->bounds.origin.y + self->corner[GSK_CORNER_TOP_LEFT].height- point->y
+                                )))
+    return FALSE;
+
+  if (self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_TOP_RIGHT].width < point->x &&
+      self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height > point->y &&
+      !ellipsis_contains_point (&self->corner[GSK_CORNER_TOP_RIGHT],
+                                &GRAPHENE_POINT_INIT (
+                                    self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_TOP_RIGHT].width - point->x,
+                                    self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height- point->y
+                                )))
+    return FALSE;
+
+  if (self->bounds.origin.x + self->corner[GSK_CORNER_BOTTOM_LEFT].width > point->x &&
+      self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_LEFT].height > point->y &&
+      !ellipsis_contains_point (&self->corner[GSK_CORNER_BOTTOM_LEFT],
+                                &GRAPHENE_POINT_INIT (
+                                    self->bounds.origin.x + self->corner[GSK_CORNER_BOTTOM_LEFT].width - point->x,
+                                    self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_LEFT].height- point->y
+                                )))
+    return FALSE;
+
+  if (self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_BOTTOM_RIGHT].width < point->x &&
+      self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_RIGHT].height > point->y &&
+      !ellipsis_contains_point (&self->corner[GSK_CORNER_BOTTOM_RIGHT],
+                                &GRAPHENE_POINT_INIT (
+                                    self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_BOTTOM_RIGHT].width - point->x,
+                                    self->bounds.origin.y + self->bounds.size.height - self->corner[GSK_CORNER_BOTTOM_RIGHT].height- point->y
+                                )))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * gsk_rounded_rect_contains_rect:
+ * @self: a #GskRoundedRect
+ * @rect: the rectangle to check
+ *
+ * Checks if the given @rect is contained inside the rounded rectangle.
+ * This function returns %FALSE if @rect extends into one of the rounded
+ * corner areas.
+ *
+ * Returns: %TRUE if the @rect is fully contained inside the rounded rectangle
+ **/
+gboolean
+gsk_rounded_rect_contains_rect (const GskRoundedRect  *self,
+                                const graphene_rect_t *rect)
+{
+  if (!graphene_rect_contains_rect (&self->bounds, rect))
+    return FALSE;
+
+  if (!gsk_rounded_rect_contains_point (self, &rect->origin) ||
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y)) ||
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + rect->size.height)) ||
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y + rect->size.height)))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * gsk_rounded_rect_intersects_rect:
+ * @self: a #GskRoundedRect
+ * @rect: the rectangle to check
+ *
+ * Checks if part of the given @rect is contained inside the rounded rectangle.
+ * This function returns %FALSE if @rect only extends into one of the rounded
+ * corner areas but not into the rounded rectangle itself.
+ *
+ * Returns: %TRUE if the @rect intersects with the rounded rectangle
+ **/
+gboolean
+gsk_rounded_rect_intersects_rect (const GskRoundedRect  *self,
+                                  const graphene_rect_t *rect)
+{
+  if (!graphene_rect_intersection (&self->bounds, rect, NULL))
+    return FALSE;
+
+  if (!gsk_rounded_rect_contains_point (self, &rect->origin) &&
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y)) &&
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + rect->size.height)) &&
+      !gsk_rounded_rect_contains_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y + rect->size.height)))
+    return FALSE;
+
+  return TRUE;
+}
+
 static void
 append_arc (cairo_t *cr, double angle1, double angle2, gboolean negative)
 {
index 9a3d33eb01fa1f153d7d3e59ce871ffa1af69376..98819e4ea3ab88d7174de78de2d1c39f3b2bfae4 100644 (file)
@@ -95,7 +95,16 @@ GskRoundedRect *        gsk_rounded_rect_shrink                 (GskRoundedRect
                                                                  float                     left);
 
 GDK_AVAILABLE_IN_3_90
-gboolean                gsk_rounded_rect_is_rectilinear         (GskRoundedRect           *self);
+gboolean                gsk_rounded_rect_is_rectilinear         (const GskRoundedRect     *self);
+GDK_AVAILABLE_IN_3_90
+gboolean                gsk_rounded_rect_contains_point         (const GskRoundedRect     *self,
+                                                                 const graphene_point_t   *point);
+GDK_AVAILABLE_IN_3_90
+gboolean                gsk_rounded_rect_contains_rect          (const GskRoundedRect     *self,
+                                                                 const graphene_rect_t    *rect);
+GDK_AVAILABLE_IN_3_90
+gboolean                gsk_rounded_rect_intersects_rect        (const GskRoundedRect     *self,
+                                                                 const graphene_rect_t    *rect);
 
 G_END_DECLS
 
index c0cccd78355eac94f70a799336e03c59e4cb9af8..f132bfc9903b579ad554b274f8fb359bbb6b26ff 100644 (file)
@@ -913,8 +913,8 @@ _gtk_css_shadow_value_paint_box (const GtkCssValue   *shadow,
     return;
 
   cairo_clip_extents (cr, &x1c, &y1c, &x2c, &y2c);
-  if ((shadow->inset && !_gtk_rounded_box_intersects_rectangle (padding_box, x1c, y1c, x2c, y2c)) ||
-      (!shadow->inset && _gtk_rounded_box_contains_rectangle (padding_box, x1c, y1c, x2c, y2c)))
+  if ((shadow->inset && !gsk_rounded_rect_intersects_rect (padding_box, &GRAPHENE_RECT_INIT (x1c, y1c, x2c - x1c, y2c - y1c))) ||
+      (!shadow->inset && gsk_rounded_rect_contains_rect (padding_box, &GRAPHENE_RECT_INIT (x1c, y1c, x2c - x1c, y2c - y1c))))
     return;
 
   cairo_save (cr);
index 5dafd63d2570fe19ee802eefa808d2ba514889ed..e51722f6a610e34350d0bfdcc926bb1ac40969d2 100644 (file)
@@ -592,50 +592,3 @@ _gtk_rounded_box_clip_path (const GskRoundedRect *box,
                    box->bounds.size.width, box->bounds.size.height);
 }
 
-gboolean
-_gtk_rounded_box_intersects_rectangle (const GskRoundedRect *box,
-                                       gdouble               x1,
-                                       gdouble               y1,
-                                       gdouble               x2,
-                                       gdouble               y2)
-{
-  if (x2 < box->bounds.origin.x ||
-      y2 < box->bounds.origin.y ||
-      x1 >= box->bounds.origin.x + box->bounds.size.width ||
-      y1 >= box->bounds.origin.y + box->bounds.size.height)
-    return FALSE;
-
-  return TRUE;
-}
-
-gboolean
-_gtk_rounded_box_contains_rectangle (const GskRoundedRect *box,
-                                     gdouble               x1,
-                                     gdouble               y1,
-                                     gdouble               x2,
-                                     gdouble               y2)
-{
-  if (x1 < box->bounds.origin.x ||
-      y1 < box->bounds.origin.y ||
-      x2 > box->bounds.origin.x + box->bounds.size.width ||
-      y2 > box->bounds.origin.y + box->bounds.size.height)
-    return FALSE;
-
-  if (x1 < box->bounds.origin.x + box->corner[GSK_CORNER_TOP_LEFT].width &&
-      y1 < box->bounds.origin.y + box->corner[GSK_CORNER_TOP_LEFT].height)
-    return FALSE;
-
-  if (x2 > box->bounds.origin.x + box->bounds.size.width - box->corner[GSK_CORNER_TOP_RIGHT].width &&
-      y1 < box->bounds.origin.y + box->corner[GSK_CORNER_TOP_RIGHT].height)
-    return FALSE;
-
-  if (x2 > box->bounds.origin.x + box->bounds.size.width - box->corner[GSK_CORNER_BOTTOM_RIGHT].width &&
-      y2 > box->bounds.origin.y + box->bounds.size.height - box->corner[GSK_CORNER_BOTTOM_RIGHT].height)
-    return FALSE;
-
-  if (x1 < box->bounds.origin.x + box->corner[GSK_CORNER_BOTTOM_LEFT].width &&
-      y2 > box->bounds.origin.y + box->bounds.size.height - box->corner[GSK_CORNER_BOTTOM_LEFT].height)
-    return FALSE;
-
-  return TRUE;
-}
index 474c56cc790ccafcb235f3dd8e1354d2e1e20702..98ebec0d9e84eb1ccc1b60dcaca9321655913564 100644 (file)
@@ -62,16 +62,6 @@ void            _gtk_rounded_box_path_left                      (const GskRounde
                                                                  cairo_t                *cr);
 void            _gtk_rounded_box_clip_path                      (const GskRoundedRect   *box,
                                                                  cairo_t                *cr);
-gboolean        _gtk_rounded_box_intersects_rectangle           (const GskRoundedRect   *box,
-                                                                 gdouble                 x1,
-                                                                 gdouble                 y1,
-                                                                 gdouble                 x2,
-                                                                 gdouble                 y2);
-gboolean        _gtk_rounded_box_contains_rectangle             (const GskRoundedRect   *box,
-                                                                 gdouble                 x1,
-                                                                 gdouble                 y1,
-                                                                 gdouble                 x2,
-                                                                 gdouble                 y2);
 
 G_END_DECLS